home *** CD-ROM | disk | FTP | other *** search
- unit dmDemo;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- DBTables, Db;
-
- type
- TCodeTablesCache = class(TStringList)
- protected
- procedure FreeObjects;
- public
- constructor Create;
- destructor Destroy; override;
- procedure Clear; override;
- function GetCodeDesc(aTableName, aCode: string): string;
- procedure GetCodeTable(aTableName: string; aTableList: TStrings);
- procedure GetCodeTableDescs(aTableName: string; aTableList: TStrings);
- function GetCodeValueFromDesc(aTableName, aCodeDesc: string): string;
- procedure Load;
- end;
-
- TDemoDM = class(TDataModule)
- Database1: TDatabase;
- qryQualifiers: TQuery;
- qryQualifiersQuaCode: TStringField;
- qryQualifiersquaFilterID: TSmallintField;
- qryQualifiersQuaFilterName: TStringField;
- qryQualifiersquaRecID: TAutoIncField;
- qryQualifiersquaID: TSmallintField;
- dsQualifiers: TDataSource;
- upsQualifiers: TUpdateSQL;
- qryFilterNameLookup: TQuery;
- qryFilterNameLookupqlfID: TSmallintField;
- qryFilterNameLookupqlfDescription: TStringField;
- qryFilterNameLookupqlfCodeTable: TStringField;
- qryQuaIDLookup: TQuery;
- qryMaxQuaIDLookup: TQuery;
- qryQualifiersqlfCodeTable: TStringField;
- procedure qryQualifiersAfterOpen(DataSet: TDataSet);
- procedure qryQualifiersAfterScroll(DataSet: TDataSet);
- procedure qryQualifiersAfterClose(DataSet: TDataSet);
- procedure qryQualifiersQuaFilterIDChange(Sender: TField);
- procedure DemoDMCreate(Sender: TObject);
- procedure DemoDMDestroy(Sender: TObject);
- procedure qryQualifiersQuaCodeGetText(Sender: TField; var Text: String;
- DisplayText: Boolean);
- procedure qryQualifiersQuaCodeSetText(Sender: TField;
- const Text: String);
- private
- protected
- CodeTablesCache: TCodeTablesCache;
- procedure LoadPickList;
- public
- end;
-
- var
- DemoDM: TDemoDM;
-
- implementation
-
- uses Demo1;
-
- {$R *.DFM}
-
- { TCodeTablesCache }
-
- { The code values cache is simply a list of all possible code values and
- their descriptions for all filter fields available for use. This data
- seldom changes and it greatly simplifies coding and performance if we avoid
- data-aware lookup fields and handle the code values internally.
-
- The code value cache structure is a nested stringlist of stringlists.
- We start with a single stringlist containing names for all the code tables.
- The Object property of each string list entry then points to another
- stringlist containing the actual code values and descriptions (in the form
- <value>=<description>) for that code table. }
-
- constructor TCodeTablesCache.Create;
- begin
- inherited Create;
- Sorted := True;
- end;
-
- destructor TCodeTablesCache.Destroy;
- begin
- FreeObjects;
- inherited Destroy;
- end;
-
- procedure TCodeTablesCache.Clear;
- begin
- FreeObjects;
- inherited Clear;
- end;
-
- procedure TCodeTablesCache.FreeObjects;
- var
- I: Integer;
- begin
- for I := 0 to Count - 1 do
- TStringList(Objects[I]).Free;
- end;
-
- function TCodeTablesCache.GetCodeDesc(aTableName, aCode: string): string;
- { Given a code table and code value, returns the description for that code }
- var
- I: Integer;
- begin
- I := IndexOf(aTableName);
- if I <> -1 then
- with TStrings(Objects[I]) do
- Result := Values[aCode];
- end;
-
- procedure TCodeTablesCache.GetCodeTable(aTableName: string; aTableList: TStrings);
- { Given a code table name, returns the full list of code values and descriptions }
- var
- I: Integer;
- begin
- I := IndexOf(aTableName);
- if I <> -1 then
- aTableList.AddStrings(TStrings(Objects[I]));
- end;
-
- procedure TCodeTablesCache.GetCodeTableDescs(aTableName: string; aTableList: TStrings);
- { Given a code table name, returns the full list of code descriptions only. }
- var
- I, J: Integer;
- begin
- I := IndexOf(aTableName);
- if I <> -1 then
- with TStrings(Objects[I]) do
- for J := 0 to Count - 1 do
- aTableList.Add(Values[Names[J]]);
- end;
-
- function TCodeTablesCache.GetCodeValueFromDesc(aTableName, aCodeDesc: string): string;
- { Given a code table name and code description, returns the code value for that
- description. }
- var
- I, J: Integer;
- begin
- I := IndexOf(aTableName);
- if I <> -1 then
- with TStrings(Objects[I]) do
- for J := 0 to Count - 1 do
- if CompareText(Values[Names[J]], aCodeDesc) = 0 then
- begin
- Result := Names[J];
- Break;
- end;
- end;
-
- procedure TCodeTablesCache.Load;
- { Loads the code table cache from the database }
- var
- I: Integer;
- begin
- Clear;
- with TQuery.Create(nil) do
- try
- DatabaseName := 'Test';
-
- { First, get list of all code tables used by all available filter fields }
- SQL.Clear;
- SQL.Add('SELECT DISTINCT qlfCodeTable');
- SQL.Add(' FROM QualifierFilters');
- SQL.Add(' ORDER BY qlfCodeTable');
- Open;
- while not Eof do
- begin
- Add(Fields[0].AsString);
- Next;
- end;
- Close;
-
- { Now, go get all the code values and descriptions for each code table }
- SQL.Clear;
- SQL.Add('SELECT codCode, codDesc FROM SystemCodes');
- SQL.Add(' WHERE codTable = :CodeTable');
- SQL.Add(' ORDER BY codDesc');
- for I := 0 to Count - 1 do
- begin
- Objects[I] := TStringList.Create;
- Params[0].AsString := Strings[I];
- Open;
- while not Eof do
- begin
- TStrings(Objects[I]).Add(Format('%s=%s', [Fields[0].AsString, Fields[1].AsString]));
- Next;
- end;
- Close;
- end;
- finally
- Free;
- end;
- end;
-
- { TDemoDM }
-
- procedure TDemoDM.LoadPickList;
- begin
- with frmMain.DBGrid1.Columns[1] do
- begin
- PickList.Clear;
- CodeTablesCache.GetCodeTableDescs(qryQualifiersQlfCodeTable.AsString, PickList);
- end;
- end;
-
- procedure TDemoDM.qryQualifiersAfterOpen(DataSet: TDataSet);
- begin
- qryFilterNameLookup.Open;
- end;
-
- procedure TDemoDM.qryQualifiersAfterScroll(DataSet: TDataSet);
- { Whenever we move to a new row, we need to set up the code value
- pick list applicable to the filter field defined in that row. }
- begin
- LoadPickList;
- end;
-
- procedure TDemoDM.qryQualifiersAfterClose(DataSet: TDataSet);
- begin
- qryFilterNameLookup.Close;
- end;
-
- procedure TDemoDM.qryQualifiersQuaFilterIDChange(Sender: TField);
- { Whenever we select or change a filter, we need to set the code table
- association too. }
- begin
- qryFilterNameLookup.Locate('qlfID', qryQualifiers.FieldByName('quaFilterID').Value, []);
- qryQualifiersQlfCodeTable.AsString := qryFilterNameLookupQlfCodeTable.AsString;
- LoadPickList;
-
- { Whatever code value we had is no longer relevant }
- qryQualifiersQuaCode.AsString := '';
- end;
-
- procedure TDemoDM.DemoDMCreate(Sender: TObject);
- begin
- CodeTablesCache := TCodeTablesCache.Create;
- CodeTablesCache.Load;
- end;
-
- procedure TDemoDM.DemoDMDestroy(Sender: TObject);
- begin
- CodeTablesCache.Free;
- end;
-
- procedure TDemoDM.qryQualifiersQuaCodeGetText(Sender: TField;
- var Text: String; DisplayText: Boolean);
- { We display code description, but store code value }
- begin
- if Trim(Sender.AsString) = '' then
- Text := ''
- else
- Text := CodeTablesCache.GetCodeDesc(qryQualifiersQlfCodeTable.AsString, Sender.AsString);
- end;
-
- procedure TDemoDM.qryQualifiersQuaCodeSetText(Sender: TField;
- const Text: String);
- { We display code description, but store code value }
- begin
- Sender.AsString :=
- CodeTablesCache.GetCodeValueFromDesc(qryQualifiersQlfCodeTable.AsString, Text);
- end;
-
- end.
-